P4514 上帝造题的七分钟

题目描述

输入格式

输入数据的第一行为 X n m,代表矩阵大小为 n×m
从输入数据的第二行开始到文件尾的每一行会出现以下两种操作:

请注意,k 为小写。

1n20481m2048500delta500,操作不超过 2×105 个,保证运算过程中及最终结果均不超过 32 位带符号整数类型的表示范围。

输出格式

针对每个 k 操作,在单独的一行输出答案。

Solution

二维树状数组+二维差分

(待更 )

#define lowbit(x) x&(-x)
int n, m;
int tr1[2100][2100], tr2[2100][2100], tr3[2100][2100], tr4[2100][2100];
void add(int x, int y, int k) {
    for (int i = x;i <= n;i += lowbit(i)) {
        for (int j = y;j <= m;j += lowbit(j)) {
            tr1[i][j] += k;
            tr2[i][j] += x * k;
            tr3[i][j] += y * k;
            tr4[i][j] += x * y * k;
        }
    }
}
void add(int a, int b, int c, int d, int k) {
    add(a, b, k);
    add(c + 1, d + 1, k);
    add(a, d + 1, -k);
    add(c + 1, b, -k);
}
int sum(int x, int y) {
    int ans = 0;
    for (int i = x;i;i -= lowbit(i)) {
        for (int j = y;j;j -= lowbit(j)) {
            ans += (x + 1) * (y + 1) * tr1[i][j] - (y + 1) * tr2[i][j] - (x + 1) * tr3[i][j] + tr4[i][j];
        }
    }
    return ans;
}
int query(int a, int b, int c, int d) {
    return sum(c, d) - sum(a - 1, d) - sum(c, b - 1) + sum(a - 1, b - 1);
}
void solve() {
    char op;cin >> op >> n >> m;
    while (cin >> op) {
        if (op == 'L') {
            int a, b, c, d, delta;cin >> a >> b >> c >> d >> delta;
            add(a, b, c, d, delta);
        } else {
            int a, b, c, d;cin >> a >> b >> c >> d;
            cout << query(a, b, c, d) << '\n';
        }
    }
}